﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace Clandestine.Entities
{
    public class EntityManager
    {
        /// <summary>
        /// The currently loaded entities (for this instance of the class, obviously).
        /// </summary>
        public Dictionary<string, Entity> LoadedEntities = new Dictionary<string, Entity>();

        /// <summary>
        /// The saved states of all non-loaded entities.
        /// </summary>
        public static Dictionary<string, Dictionary<string, string>> EntityStates = new Dictionary<string, Dictionary<string, string>>();

        /// <summary>
        /// Get an entity by it's name property.
        /// </summary>
        /// <param name="name">The name of the entity to search for.</param>
        /// <returns></returns>
        public Entity GetByName(string name)
        {
            foreach (Entity e in LoadedEntities.Values)
                if (e.Name.ToLower() == name.ToLower())
                    return e;
            throw new ArgumentOutOfRangeException();
        }

        /// <summary>
        /// Adds an entity to the LoadedEntities dictionary and checks for appropriate State data.
        /// </summary>
        /// <param name="e">The entity to be added.</param>
        public void AddEntity(Entity e)
        {
            if (!LoadedEntities.ContainsKey(e.UUID))
            {
                LoadedEntities.Add(e.UUID, e);
                if (EntityStates.ContainsKey(e.UUID))
                    loadState(e);
            }
            else
                Log.e("We tried to load/add an entity when an entity with that UUID already exists!");
        }

        /// <summary>
        /// Saves the states of all LoadedEntities who PreserveState and stores them back in the EntityStates dictionary, before clearing the LoadedEntities dictionary.
        /// </summary>
        public void UnloadAllEntities()
        {
            foreach (KeyValuePair<string, Entity> kvp in LoadedEntities)
            {
                if (kvp.Value.PreserveState)
                    saveState(kvp.Value);
                kvp.Value.Dispose();
            }
            LoadedEntities.Clear();
            Log.i("Cleared entity list.");
        }

        /// <summary>
        /// Saves the states of all entities to an xml file -- probably the save game file.
        /// </summary>
        /// <param name="xml">An XmlTextWriter.</param>
        public static void SaveStates(XmlTextWriter xml)
        {
            // Remember to save the states of those not in EntityStates (i.e. currently loaded)
            throw new NotImplementedException();
        }

        /// <summary>
        /// Saves the state of an entity.
        /// </summary>
        /// <param name="e">The entity to save the state of.</param>
        private static void saveState(Entity e)
        {
            if (EntityStates.ContainsKey(e.UUID))
            {
                EntityStates.Add(e.UUID, e.SaveState());
            }
            else
                Log.e("We were told to save the state of an Entity that is loaded, but we already have state information for an entity with that UUID!");
        }

        /// <summary>
        /// Loads the state of an entity and removes it from the EntityStates dictionary.
        /// </summary>
        /// <param name="e">The entity to load the state of.</param>
        private static void loadState(Entity e)
        {
            if (EntityStates.ContainsKey(e.UUID))
            {
                e.LoadState(EntityStates[e.UUID]);
                EntityStates.Remove(e.UUID);
            }
            else
                Log.e("We were told to load an entity's state data but no such data exists!");
        }
    }
}
